Skip to content

MC-30: Sync Database-entity-details; drop the vendored pipeline-records schema - #14

Merged
touchdownllc merged 2 commits into
Ed-Fi-Alliance-OSS:mainfrom
touchdownllc:MC-30-fact-run-identity-schema-sync
Aug 3, 2026
Merged

MC-30: Sync Database-entity-details; drop the vendored pipeline-records schema#14
touchdownllc merged 2 commits into
Ed-Fi-Alliance-OSS:mainfrom
touchdownllc:MC-30-fact-run-identity-schema-sync

Conversation

@touchdownllc

@touchdownllc touchdownllc commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

What this is

MC-30 is now scoped to the documentation side only. This PR does two things:

  1. Updates docs/design/Database-entity-details.md to match five changes that
    have landed on the pipeline side
    , so the entity and field tables describe
    what the pipeline actually emits.
  2. Deletes docs/design/schemas/pipeline-records.schema.json. The schema
    arrives with the POC-3 migration ([MC-1] NACHOS automated scoring engine - initial code migration #11), which brings in the generator that
    produces it.

One commit each.


1. The doc sync

Fact-run identity — fact_runs gains the dedup key

A fact-run header carries mode, model, prompt_version, status,
cost_cap_hit and the run counts. Nothing the landing side deduped on covered
any of it: ingestion_runs.run_id comes purely from the ingestion inputs, and
the per-(state, lens) release_id covers scored records.

That gap was observed, not theorised. Correcting fact_run.mode from "api" to
"llm" (MC-24 §8.8) changed 135 fact-run headers while every identity the loader
compares stayed byte-identical. The load concluded the run was already landed and
skipped the correction.

Two digest columns close it (nachos-ai-poc-3#345, ADR 0023):

  • observations_digest — sha256 over the observation rows. What was extracted.
  • fact_run_digest — sha256 over the identity-recipe version, every
    non-volatile header field, and observations_digest. The dedup key. Equal
    means the held row is current, skip. Different means re-land, including when
    ingestion_run_id and the snapshot digests are unchanged — the case that
    broke. Comparing the pair separates a header-only correction (observations
    equal, run digest moved) from changed data (both moved).

The digest does not cover scored_at or the token/cost/cache counters: those
describe the occurrence, and a cache-warm replay of identical facts reports $0
and different token counts without being new data.

Adds a Fact-run identity section plus the two fact_runs rows.

base_nachos_score on score_records

adjusted_nachos_score was already a column; the base methodology tier it is
built from (0–3) was reachable only inside the open dimensions blob
(dimensions.nachos_score.value), so one half of the base/adjusted headline was
a plain column and the other needed a JSON dig.

Landing-derived from dimensions.nachos_score.value the same way
documentation_gap is, so nothing changes on the emit side.

Distinct from complexity_score: nachos_score is the NACHOS methodology tier
that feeds adjusted_nachos_score; complexity_score is the
business_logic_complexity comprehension-cost signal. Same input facts,
different rubric — they coincide on ~99% of rows but diverge where the
methodology rules differ: 238 / 24,990 rows in release r-37334d4a830f060d.

source_document_description and school_year on source_elements

Operator-supplied provenance for the documentation package an artifact was built
from — a plain-English label like "TEA publication Jan 2026" and, optionally, the
school year it targets — sourced from the pipeline's committed
data/source_documents.yaml registry. Both are uniform across every record of one
artifact; display-only, never scored. source_document_description is required
non-blank, school_year is required-but-nullable.

nachos-ai-poc-3#351 (ADR 0016).

documented on score_records; sidecar contract 3 → 4

documented is the headline predicate. Aggregate computes every reported mean,
dimension distribution and review count over the rows where it is true (the
header's in_scope_count is their count), but no per-record field let a consumer
reproduce that population from a sidecar alone. documentation_source looks like
it should serve and does not: on the API-model lens every row is source_doc, so
a consumer keying on it computes the headline population correctly on one lens and
silently wrongly on the other.

Per ADR 0017 the contract-version bump does not stale adjudications.

nachos-ai-poc-3#364 (ADR 0025).

prompt_fingerprint and answered_by_host on fact_runs; fact identity 1 → 2

  • prompt_fingerprint — sha256 over the rendered prompt batches that produced the
    observations; the producer's own freshness key, which freshness previously could
    not detect a change to.
  • answered_by_host — which endpoint served the run (anthropic,
    azure:<host>/<deployment>, deterministic, the cache:/mixed: replay tags,
    or unknown). Records what model cannot: an Azure-hosted run still reports
    the base model id.

Both are nullable and covered by the ADR 0023 deny-list by construction, so the
digest recipe is unchanged; the fact-identity version moves 1 → 2 purely as an
epoch marker. One-time consequence: every fact_run_digest in the tree changes at
once while every observations_digest stays put, so a loader re-lands each fact
run once rather than reading independent content changes.

This also corrects the fact_runs.contract_version row, which described the
sidecar meaning — the exact touchdownllc/dataload_poc#27 conflation. A fact run has
no sidecar; its contract_version is the fact-identity recipe epoch.

nachos-ai-poc-3#378/#381 (ADR 0027); host tags #392, refined by #394.


2. Deleting the vendored schema

docs/design/schemas/pipeline-records.schema.json was a second copy of an artifact
the pipeline generates and owns (publish/pipeline_records_contract.py), kept
byte-identical by hand because the generator and the consumer of the contract lived
in separate repos. The POC-3 migration brings the generator into this repo, so the
copy stops being a sync target — it would be a stale sibling of a file generated a
directory away.

Database-entity-details.md pointed at it by repo path in five places. Those now
name the companion schema without pinning a path, since the migration settles where
it lands, and the two-repo byte-identity discipline goes with the copy.

MC-18 is unaffected in substance. The contract test still validates
pipeline-emitted records against the schema on every build; what it no longer has is
a second copy to enforce byte identity against. That is a simplification of MC-18,
not a gap — it should be picked up when the migration lands and the schema's path in
this repo is known.


Files

  • docs/design/Database-entity-details.md — the five changes above, plus the
    path-free rewording of the five schema references.
  • docs/design/schemas/pipeline-records.schema.json — deleted.

@touchdownllc
touchdownllc marked this pull request as draft July 24, 2026 17:45
@touchdownllc touchdownllc changed the title MC-30: fact-run content identity — fact_runs gains the dedup key MC-30: sync pipeline-records schema — fact-run identity, base_nachos_score, source-document metadata Jul 24, 2026
@touchdownllc touchdownllc changed the title MC-30: sync pipeline-records schema — fact-run identity, base_nachos_score, source-document metadata MC-30: Sync the pipeline-records schema Jul 24, 2026
touchdownllc and others added 2 commits July 27, 2026 17:44
Documents five changes that have landed on the pipeline side, so the entity
and field tables describe what the pipeline now emits.

Fact-run identity (nachos-ai-poc-3#345, ADR 0023). fact_runs gains
observations_digest and fact_run_digest, plus a Fact-run identity section
naming fact_run_digest as the dedup key. Nothing the landing side deduped on
covered a fact-run header: correcting fact_run.mode from "api" to "llm"
(MC-24 §8.8) changed 135 headers while every identity the loader compares
stayed byte-identical, so the load decided the run was already there and
skipped the correction.

base_nachos_score on score_records. adjusted_nachos_score was already a
column; the base methodology tier it is built from was reachable only inside
the open dimensions blob, so one half of the base/adjusted pair needed a JSON
dig. Landing-derived from dimensions.nachos_score.value, the same way
documentation_gap is, so nothing changes on the emit side.

source_document_description and school_year on source_elements
(nachos-ai-poc-3#351, ADR 0016) — operator-supplied provenance for the
documentation package an artifact was built from, sourced from the pipeline's
committed data/source_documents.yaml registry. Display-only, never scored.

documented on score_records (nachos-ai-poc-3#364, ADR 0025) — the headline
predicate aggregate computes every reported mean, dimension distribution, and
review count over. documentation_source cannot stand in for it: on the API-
model lens every row is source_doc. Sidecar contract version 3 -> 4, which
per ADR 0017 does not stale adjudications.

prompt_fingerprint and answered_by_host on fact_runs (nachos-ai-poc-3#378 and
 #381, ADR 0027; host tags #392, refined by #394); fact identity version
1 -> 2 as an epoch marker, both fields nullable and covered by the ADR 0023
deny-list so the digest recipe is unchanged. Also corrects the
fact_runs.contract_version row, which described the sidecar meaning — the
exact touchdownllc/dataload_poc#27 conflation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
docs/design/schemas/pipeline-records.schema.json was a second copy of an
artifact the pipeline generates and owns (publish/pipeline_records_contract.py),
kept byte-identical by hand because the generator and the consumer of the
contract lived in separate repos. The POC-3 migration brings the generator into
this repo, so the copy stops being a sync target — it would be a stale sibling
of a file generated a directory away. Delete it and let the migration land the
one copy.

Database-entity-details pointed at it by repo path in five places. Those now
name the companion schema without pinning a path, since the migration settles
where it lands, and the two-repo byte-identity discipline goes with the copy.
MC-18 still validates emitted records against the schema; what it no longer has
is a second copy to enforce identity against.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@touchdownllc
touchdownllc force-pushed the MC-30-fact-run-identity-schema-sync branch from 5be1113 to 8e6b020 Compare July 28, 2026 00:46
@touchdownllc touchdownllc changed the title MC-30: Sync the pipeline-records schema MC-30: Sync Database-entity-details; drop the vendored pipeline-records schema Jul 28, 2026
@touchdownllc
touchdownllc marked this pull request as ready for review July 31, 2026 22:45
@touchdownllc
touchdownllc merged commit 9e001e2 into Ed-Fi-Alliance-OSS:main Aug 3, 2026
1 check passed
@touchdownllc
touchdownllc deleted the MC-30-fact-run-identity-schema-sync branch August 3, 2026 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants